const fs = require('fs');
const path = require('path');
const mockjs = require('mockjs');
const { mock_path } = require('../config.json');
const { merge } = require('lodash');

const matchMock = (req, res) => {
    const targetPath = req.path,
        method = req.method;
    const targetMethod = method.toLowerCase();

    console.log(targetPath);
    console.log(targetMethod);
    console.log(req.body);

    return findMock(targetPath, req, res);

    // let value = null;
    // _.keys(mockData).every((key) => {
    //  console.log(key);
    //  const arr = key.split(/\s+/);
    //  const method = arr[0].toLowerCase();
    //  const re = new RegExp(arr[1]);
    //     if (method === targetMethod) {
    //       const match = re.exec(targetPath);
    //       if (match) {
    //         value = mockData[key];
    //   return false;
    //       }
    //     }
    //  return true;
    // })

    // return value;
};

const updateMockData = async () => {
    var mockData = {};

    await fs.readdirSync(mock_path).forEach(async function(filename) {
        if (!/\.js$/.test(filename)) {
            return;
        }

        var name = path.basename(filename, '.js');
        await import(path.join(mock_path, name)).then((module) => {
            const loadData = module.default;
            merge(mockData, loadData);
        })
    });

    return mockData;
}

const findMock = (targetPath, req, res) => {
    let mockFile = path.join(mock_path, targetPath + '.json');
    let mockData;
    if (fs.existsSync(mockFile)) {
        console.log(mockFile);
        let rawdata = fs.readFileSync(mockFile);
        try {
            mockData = JSON.parse(rawdata);
        } catch (e) {
            eval('mockData=' + rawdata);
            console.log(mockData);
        }
    } else {
        mockFile = path.join(mock_path, targetPath + '.js');
        if (fs.existsSync(mockFile)) {
            console.log(mockFile);
            require(path.join(mock_path, targetPath))(req, res);
            return;
        } else {
            console.log('Not found mock file for ' + path.join(mock_path, targetPath));
        }
    }
    return mockData;
}

const evalKey = (handler, props) => {
    if (handler == null) return;

    Object.keys(handler).map(key => {
        if (typeof handler[key] === 'function') {
            handler = merge(handler, {
                [key]: handler[key](props) })
        } else if (typeof handler[key] === 'object') {
            evalKey(handler[key], props);
        }
    });
    return handler;
}

const createMiddleware = async () => {
    console.log("Mock Path: ", mock_path);

    // var mockData = await updateMockData();
    // console.log(mockData);
    return {
        middleware: (req, res, next) => {
            const handler = matchMock(req, res);
            if (handler) {
                evalKey(handler, { _req: req, Mock: mockjs });
                res.json(handler);
            } else {
                return next();
            }
        }
    };
}

export default createMiddleware;